package com.lqwu.mallchatserver.chat.strategy.msg;

import cn.hutool.core.bean.BeanUtil;
import com.lqwu.mallchatserver.chat.model.entry.Message;
import com.lqwu.mallchatserver.chat.service.MessageService;
import com.lqwu.mallchatserver.chat.service.adaptor.MessageAdapter;
import com.lqwu.mallchatserver.chat.service.strategy.MsgHandlerFactory;
import com.lqwu.mallchatserver.common.utils.AssertUtil;
import com.lqwu.mallchatserver.user.model.dto.ChatMessageReq;
import com.lqwu.mallchatserver.user.model.enums.MessageTypeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.lang.reflect.ParameterizedType;

/**
 * Description: 消息处理器抽象类
 * Author: <a href="https://github.com/zongzibinbin">abin</a>
 * Date: 2023-06-04
 */
public abstract class AbstractMsgHandler<Req> {
    @Resource
    private MessageService messageService;
    private Class<Req> bodyClass;

    /**
     *
     */
    @PostConstruct
    private void init() {
        ParameterizedType genericSuperclass = (ParameterizedType) this.getClass().getGenericSuperclass();
        this.bodyClass = (Class<Req>) genericSuperclass.getActualTypeArguments()[0];
        MsgHandlerFactory.register(getMsgTypeEnum().getType(), this);
    }

    /**
     * 消息类型
     */
    abstract MessageTypeEnum getMsgTypeEnum();

    protected void checkMsg(Req body, Long roomId, Long uid) {

    }


    private Req toBean(Object body) {
        if (bodyClass.isAssignableFrom(body.getClass())) {
            return (Req) body;
        }
        return BeanUtil.toBean(body, bodyClass);
    }

    protected abstract void saveMsg(Message message, Req body);

    /**
     * 展示消息
     */
    public abstract Object showMsg(Message msg);

    /**
     * 被回复时——展示的消息
     */
    public abstract Object showReplyMsg(Message msg);

    /**
     * 会话列表——展示的消息
     */
    public abstract String showContactMsg(Message msg);

    /**
     * 检查并保存消息
     */
    @Transactional
    public Long checkAndSaveMsg(ChatMessageReq chatMessageReq, Long uid) {
        // 1.获取消息的内容抽象对象
        Req body = toBean(chatMessageReq.getBody());
        // 2.校验
        AssertUtil.allCheckValidateThrow(body);
        // 3.子类扩展校验
        checkMsg(body, chatMessageReq.getRoomId(), uid);
        Message insert = MessageAdapter.buildMsgSave(chatMessageReq, uid);
        // 4.统一保存
        messageService.save(insert);
        // 5.子类扩展保存
        saveMsg(insert, body);
        return insert.getId();
    }
}
